package yl.hs.bmipfull.utils;

import javax.servlet.http.HttpServletRequest;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import yl.hs.bmipfull.annotations.DBTable;
import yl.hs.bmipfull.pojo.system.AppSettingEntity;
import yl.hs.bmipfull.pojo.system.UserInfoEntity;
import yl.hs.bmipfull.security.TokenUtils;
import yl.hs.bmipfull.service.system.IAppSettingService;
import yl.hs.bmipfull.service.system.IOrganizationInfoService;
import yl.hs.bmipfull.service.system.IUserService;
import yl.hs.bmipfull.service.system.impl.AppSettingServiceImpl;
import yl.hs.bmipfull.viewmodels.LoginUser;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HsApp {
	public static LoginUser getCurrent() {
		ICache cache = CacheFactory.getCache();
		var request = getRequest();
		var token = request.getHeader(CK.TOKEN_HEADER_KEY);
		if(!Tl.isEmpty(token)) {
			var cacheUser = cache.get(token);
			if (cacheUser != null) {
				return (LoginUser) cacheUser;
			}
			else if (userService!=null){
				try {
					var authentication = TokenUtils.getAuthenticationFromToken(request);
					if (authentication != null) {
						var requestUrl = request.getRequestURL();
						if(requestUrl.indexOf(CK.Construction)>-1){
							var user = userService.findConstructionUserByAccount(authentication.getName());
							if(user==null){
								return null;
							}
							var companyName = user.getNickname();
							user.setNickname(user.getRealname());
							return HsApp.addCurrent(user,companyName);
						}
						else {

							var user = userService.findUserByAccount(authentication.getName());
							var company = orgSvc.findBySn(user.getCompanySN());
							return HsApp.addCurrent(user, company.getFullName());
						}
					}
				}
				catch (Exception ee){
					return  null;
				}
			}
		}
		return null;
	}

	public static String passwordEncoder(String sourcePassword){
		BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
		return encoder.encode(sourcePassword);
	}

	public static LoginUser addCurrent(UserInfoEntity user,String companyName)
	{
		if(user!=null) {
			var loginUser = new LoginUser();
			loginUser.setAccount(user.getAccount());
			loginUser.setImageSN(user.getImageSN());
			loginUser.setNickName(user.getNickname());
			loginUser.setMobileNum(user.getMobileNum());
			loginUser.setOrganizationCode(user.getOrganizationCode());
			loginUser.setTheme(user.getTheme());
			loginUser.setUseLanguage(user.getUseLanguage());
			loginUser.setUserSN(user.getSn());
			loginUser.setCompanySN(user.getCompanySN());
			loginUser.setUserName(user.getRealname());
			loginUser.setCompanyName(companyName);
			loginUser.setDutySN("");
			loginUser.setDutyName("");
			loginUser.setRoleSN(null);
			loginUser.setType(user.getType());
			ICache cache = CacheFactory.getCache();
			cache.add(user.getAccount(), loginUser);
			return loginUser;
		}
		return null;
	}


	public static void removeCurrent() {
		ICache cache = CacheFactory.getCache();
		var request = getRequest();
		var token = request.getHeader(CK.TOKEN_HEADER_KEY);
		if (!Tl.isEmpty(token)) {
			cache.remove(token);
		}
	}
	/***
	 * 获取当前的web请求
	 * @return 当前的web请求
	 */
	public static HttpServletRequest getRequest() {

		ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();

	   return	sra.getRequest();
	}

	/**
	 * 获取用户客户端地址
	 * @return 用户客户端地址
	 */
	public static String getClient() {
		var request = getRequest();
		String ip = request.getHeader("x-forwarded-for");
		if (ip != null && ip.contains(",")) {
			ip = ip.split(",")[0];
		}

		if (!checkIp(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (!checkIp(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (!checkIp(ip)) {
			ip = request.getHeader("X-Real-IP");
		}

		if (!checkIp(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

	private static boolean checkIp(String ip) {
		if (ip == null || ip.length() == 0 || "unkown".equalsIgnoreCase(ip)) {
			return false;
		}
		return true;
	}

	private static IOrganizationInfoService orgSvc;
	private static IUserService userService;

    public static void setUserService(IUserService userDetailsService,IOrganizationInfoService organizationInfoService) {
    	userService = userDetailsService;
    	orgSvc = organizationInfoService;
    }

    public static List<Class<?>> getPojoClass(){
		String CLASS="*.class";
		String PACKAGE="yl.hs.bmipfull.pojo.*.";
		ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
		String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
				ClassUtils.convertClassNameToResourcePath(PACKAGE) + CLASS;
		List<Class<?>> list = new ArrayList<>();
		try {
			Resource[] resources = resourcePatternResolver.getResources(pattern);
			MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
			for (Resource resource : resources) {
				MetadataReader reader = readerFactory.getMetadataReader(resource);
				String classname = reader.getClassMetadata().getClassName();
				Class<?> clazz = Class.forName(classname);
				DBTable dataSubjectAnnotation = clazz.getAnnotation(DBTable.class);
				if (dataSubjectAnnotation != null) {
					DBTable annotation = clazz.getAnnotation(DBTable.class);
					list.add(clazz);
				}
			}
		}catch (Exception e){
			e.printStackTrace();
		}
		return list;
	}

    public static  List<Class<?>> getAllClass(String packageName) throws ClassNotFoundException{
		ClassLoader cld = Thread.currentThread().getContextClassLoader();
		if (cld==null){
			throw new ClassNotFoundException("获取不到 ClassLoader");
		}
		//cld.
		File directory = null;
		String appRoot =  getAppRootPath();
		String path = packageName.replace(".","/");
		URL resource = cld.getResource(path);
		if (resource==null){
			throw  new ClassNotFoundException("resource不能加载");
		}

		directory = new File(resource.getFile());
		List<Class<?>> classes = new ArrayList<>(getClassesForDirectory(directory, packageName));

		return  classes;
	}
	private  static  List<Class<?>> getClassesForDirectory(File dir,String packageName) throws ClassNotFoundException {
		List<Class<?>> list = new ArrayList<>();
		if(dir.exists()){
			var files = dir.list();
			for (int i = 0; i < files.length; i++) {
				String file = files[i];
				if(file.endsWith(".class")){
					var cls = Class.forName(packageName+"."+file.substring(0,file.length()-6));
					if(cls.getAnnotation(DBTable.class)!=null){
						list.add(cls);
					}
				}
				else
				{
					var child = new File(dir.getPath()+"/"+file);
					if(child.isDirectory()){
						list.addAll(getClassesForDirectory(child,packageName+"."+file));
					}
				}
				//if(new ())
			}
		}
		return  list;
	}

	public static String getAppRootPath(){
    	return getRequest().getSession().getServletContext().getRealPath("/");
	}
	public static boolean checkSystem(){
		var application = getRequest().getServletContext();
		var sData = application.getAttribute(CK.HSERP_SYSTEM_SETTING);
    	return sData == null;
	}
    public static void setSystemSet(List<AppSettingEntity> systemSet) {
    	if(systemSet.size()>0) {
			var application = getRequest().getServletContext();
			var setInfo = new HashMap<String, String>();
			for (var item : systemSet) {
				if (!setInfo.containsKey(item.getParamCode())) {
					setInfo.put(item.getParamCode(), item.getParamValue());
				}
			}
			application.setAttribute(CK.HSERP_SYSTEM_SETTING, setInfo);
		}
    }


	public static String getSystemSet(String key) {
		var application = getRequest().getServletContext();
		var sData = application.getAttribute(CK.HSERP_SYSTEM_SETTING);
		if(sData!=null){
			return ((Map<String,String>)sData).get(key);
		}
		return null;
	}
	public String getSystemSetByDB(String key) {
		IAppSettingService appSettingService=new AppSettingServiceImpl();
		AppSettingEntity appSetting = appSettingService.getByParamCode(key);
		if(appSetting!=null){
			return appSetting.getParamValue();
		}
		return null;
	}
	public static boolean checkHostInit(){
		var application = getRequest().getServletContext();
		var state = application.getAttribute("hostInit");

		return  state!=null;
	}
	public static void setHostInit(){
		var application = getRequest().getServletContext();
		application.setAttribute("hostInit","a");
	}
	
}
